react 新特性
- Context 实现跨层级的组件数据传递,静态属性 ContextType 访问跨层级组件的数据
- Lazy 与 Suspense 实现延迟加载(类似于 vue 的异步组件)
- Memo 实现指定组件进行渲染(优化组件渲染,当传入组件的属性值都不变的情况下,不会触发组件的重新渲染,用于函数组件中替代 PureComponent,注意 PureComponent 只监听第一层属性的变化,当属性拆分越简单,使用的概率就越高)
这里暂时举例,官网都有,下面使用 Hooks 也会涉及到部分
Hooks
Hooks 的意义
类组件的不足:
- 状态逻辑难以复用
- 缺少复用机制
- 渲染属性和高阶组件会导致层级冗余
- 趋向复杂难以维护
- 生命周期函数混杂不相干逻辑
- 相干逻辑分散在不同生命周期函数中
- this 指向困扰
- 内联函数过度创建新句柄
- 类成员函数不能保证 this
Hooks 的优势:
- 优化类组件的三大问题
- 函数组件无 this 问题
- 自定义 Hook 方便复用状态逻辑
- 副作用的关注点分离
Hook 的使用
可以使用 eslint-plugin-react-hooks 来减少 hooks 的使用错误
在 package.json 中:
1 | "eslintConfig": { |
useState
useState 用来替代之前类组件中 state 成员和 setState 方法的新的状态解决方案
直接使用:
1 | import React, { Component, useState } from 'react' |
若需要从父组件中获取数据赋值:
1 | import React, { Component, useState } from 'react' |
useState 的使用主要注意两点:
- 使用需要规规矩矩,按顺序,次数不能多也不能少(使用 eslint-plugin-react-hooks 插件减少错误)
- 可以传入一个函数,实现延迟初始化提高效率
useEffect
useEffect 替代之前的副作用使用场景
副作用的时机(生命周期函数):
- Mount 之后 - componentDidMount
- Update 之后 - componentDidUpdate
- Unmount 之前 - componentWillUnmount
类组件代码:
1 | import React, { Component } from 'react' |
使用 Hooks useEffect 代码:
1 | import React, { Component, useState, useEffect } from 'react' |
之前类组件的生命周期函数在命名上比较好理解,但是其实都是围绕着组件的渲染和重渲染,useEffect 把它们抽象了一层,通过第二个参数来控制抽象的时机,这于生命周期函数是一样的。大家理解什么样的 useEffect 参数和什么周期函数是对应的,就可以灵活应用了。
Contenxt Hooks
类组件的使用方式
1 | import React, { Component, useState } from 'react' |
useContext 的实现方式
1 | import React, { Component, useState, useContext } from 'react' |
注意不要乱用 context,因为它会破坏组件的容积性
useMemo && useCallback
useMemo 的使用:
1 | import React, { Component, useState, useMemo } from 'react' |
useCallback 的使用:
1 | import React, { Component, useState, useMemo, memo, useCallback } from 'react' |
所以 useCallback 是 useMemo 的变体
useRef
useRef 用于:
- 获取子组件或者 DOM 节点的句柄
- 渲染周期之间共享数据的存储(state等)
使用 useRef 之前,不能满足 clearInterval 定时器的需求:
1 | import React, { Component, PureComponent, useState, useEffect, useMemo, memo, useCallback, useRef } from 'react' |
使用 useRef:
1 | import React, { Component, PureComponent, useState, useEffect, useMemo, memo, useCallback, useRef } from 'react' |
童鞋们如果碰到需要在组件中获取上一次渲染的一些数据,甚至是 state,就把他们放到 useRef 中,下次渲染就能正确的获取到了。
上面用到了 useRef 的两种使用场景:
- 获取子组件或者 DOM 元素
- 同步不同渲染周期之间需要共享的数据
自定义 Hooks
1 | import React, { Component, PureComponent, useState, useEffect, useRef } from 'react' |
Hook 规则
只在最顶层使用 Hook
不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。
只在 React 函数中调用 Hook
不要在普通的 JavaScript 函数中调用 Hook。你可以:
- 在 React 的函数组件中调用 Hook
- 在自定义 Hook 中调用其他 Hook
遵循此规则,确保组件的状态逻辑在代码中清晰可见。